require 'blankslate'
require 'builder'
require 'table_helper/collection_table'

# Provides a set of methods for turning a collection into a table
module TableHelper
  # Generates a new table for the given collection.
  #
  # == Basic Example
  #
  # This example shows the most basic usage of +collection_table+ which takes
  # information about a collection, the objects in them, the columns defined
  # for the class, and generates a table based on that.
  #
  # Suppose you have a table generated by a migration like so:
  #
  #   class CreatePeople < ActiveRecord::Base
  #     def self.up
  #       create_table do |t|
  #         t.string :first_name
  #         t.string :last_name
  #         t.integer :company_id
  #         t.string :role
  #       end
  #     end
  #   end
  #
  # ...then invoking the helper within a view:
  #
  #   <%= collection_table Person.find(:all) %>
  #
  # ...is compiled to (formatted here for the sake of sanity):
  #
  #   <table cellpadding="0" cellspacing="0" class="posts ui-collection">
  #   <thead>
  #     <tr>
  #       <th class="person-first_name" scope="col">First Name</th>
  #       <th class="person-last_name" scope="col">Last Name</th>
  #       <th class="person-company_id" scope="col">Company</th>
  #       <th class="person-role" scope="col">Role</th>
  #     </tr>
  #   </thead>
  #   <tbody>
  #     <tr class="person ui-collection-result">
  #       <td class="person-first_name">John</td>
  #       <td class="person-last_name">Doe</td>
  #       <td class="person-company_id">1</td>
  #       <td class="person-role">President</td>
  #     </tr>
  #     <tr class="person ui-collection-result">
  #       <td class="first_name">Jane</td>
  #       <td class="last_name">Doe</td>
  #       <td class="company_id">1</td>
  #       <td class="role">Vice-President</td>
  #     </tr>
  #   </tbody>
  #   <table>
  #
  # == Advanced Example
  #
  # This example below shows how +collection_table+ can be customized to show
  # specific headers, content, and footers.
  #
  #   <%=
  #     collection_table(@posts, :id => 'posts', :class => 'summary') do |t|
  #       t.header :title
  #       t.header :category
  #       t.header :author
  #       t.header :publish_date, 'Date<br \>Published'
  #       t.header :num_comments, '# Comments'
  #       t.header :num_trackbacks, '# Trackbacks'
  #
  #       t.rows.alternate = :odd
  #       t.rows.each do |row, post, index|
  #         row.category       post.category.name
  #         row.author         post.author.name
  #         row.publish_date   time_ago_in_words(post.published_at)
  #         row.num_comments   post.comments.empty? ? '-' : post.comments.size
  #         row.num_trackbacks post.trackbacks.empty? ? '-' : post.trackbacks.size
  #       end
  #     end
  #   %>
  #
  # ...is compiled to (formatted here for the sake of sanity):
  #
  #   <table cellpadding="0" cellspacing="0" class="summary posts ui-collection" id="posts">
  #   <thead>
  #     <tr>
  #       <th class="post-title" scope="col">Title</th>
  #       <th class="post-category" scope="col">Category</th>
  #       <th class="post-author" scope="col">Author</th>
  #       <th class="post-publish_date" scope="col">Date<br \>Published</th>
  #       <th class="post-num_comments" scope="col"># Comments</th>
  #       <th class="post-num_trackbacks" scope="col"># Trackbacks</th>
  #     </tr>
  #   </thead>
  #   <tbody>
  #     <tr class="post ui-collection-result">
  #       <td class="post-title">Open-source projects: The good, the bad, and the ugly</td>
  #       <td class="post-category">General</td>
  #       <td class="post-author">John Doe</td>
  #       <td class="post-publish_date">23 days</td>
  #       <td class="post-num_comments">-</td>
  #       <td class="post-num_trackbacks">-</td>
  #     </tr>
  #     <tr class="post ui-collection-result ui-state-alternate">
  #       <td class="post-title">5 reasons you should care about Rails</td>
  #       <td class="post-category">Rails</td>
  #       <td class="author">John Q. Public</td>
  #       <td class="post-publish_date">21 days</td>
  #       <td class="post-num_comments">-</td>
  #       <td class="post-num_trackbacks">-</td>
  #     </tr>
  #     <tr class="post ui-collection-result">
  #       <td class="post-title">Deprecation: Stop digging yourself a hole</td>
  #       <td class="post-category">Rails</td>
  #       <td class="post-author">Jane Doe</td>
  #       <td class="post-publish_date">17 days</td>
  #       <td class="post-num_comments">-</td>
  #       <td class="post-num_trackbacks">-</td>
  #     </tr>
  #     <tr class="post ui-collection-result ui-state-alternate">
  #       <td class="post-title">Jumpstart your Rails career at RailsConf 2007</td>
  #       <td class="post-category">Conferences</td>
  #       <td class="post-author">Jane Doe</td>
  #       <td class="post-publish_date">4 days</td>
  #       <td class="post-num_comments">-</td>
  #       <td class="post-num_trackbacks">-</td>
  #     </tr>
  #     <tr class="post ui-collection-result">
  #       <td class="post-title">Getting some REST</td>
  #       <td class="post-category">Rails</td>
  #       <td class="post-author">John Doe</td>
  #       <td class="post-publish_date">about 18 hours</td>
  #       <td class="post-num_comments">-</td>
  #       <td class="post-num_trackbacks">-</td>
  #     </tr>
  #   </tbody>
  #   </table>
  #
  # == Creating footers
  #
  # Footers allow you to show some sort of summary information based on the
  # data displayed in the body of the table.  Below is an example:
  #
  #   <%
  #     collection_table(@posts) do |t|
  #       t.header :title
  #       t.header :category
  #       t.header :author
  #       t.header :publish_date, 'Date<br \>Published'
  #       t.header :num_comments, '# Comments'
  #       t.header :num_trackbacks, '# Trackbacks'
  #
  #       t.rows.alternate = :odd
  #       t.rows.each do |row, post, index|
  #         row.category       post.category.name
  #         row.author         post.author.name
  #         row.publish_date   time_ago_in_words(post.published_at)
  #         row.num_comments   post.comments.empty? ? '-' : post.comments.size
  #         row.num_trackbacks post.trackbacks.empty? ? '-' : post.trackbacks.size
  #       end
  #
  #       t.footer :num_comments, @posts.inject(0) {|sum, post| sum += post.comments.size}
  #       t.footer :num_trackbacks, @posts.inject(0) {|sum, post| sum += post.trackbacks.size}
  #     end
  #   %>
  #
  # ...is compiled to:
  #
  #   <table cellpadding="0" cellspacing="0" class="posts ui-collection">
  #   <thead>
  #     <tr>
  #       <th class="post-title" scope="col">Title</th>
  #       <th class="post-category" scope="col">Category</th>
  #       <th class="post-author" scope="col">Author</th>
  #       <th class="post-publish_date" scope="col">Date<br \>Published</th>
  #       <th class="post-num_comments" scope="col"># Comments</th>
  #       <th class="post-num_trackbacks" scope="col"># Trackbacks</th>
  #     </tr>
  #   </thead>
  #   <tbody>
  #     <tr class="post ui-collection-result">
  #       <td class="post-title">Open-source projects: The good, the bad, and the ugly</td>
  #       <td class="post-category">General</td>
  #       <td class="post-author">John Doe</td>
  #       <td class="post-publish_date">23 days</td>
  #       <td class="post-num_comments">-</td>
  #       <td class="post-num_trackbacks">-</td>
  #     </tr>
  #     <tr class="post ui-collection-result ui-state-alternate">
  #       <td class="post-title">5 reasons you should care about Rails</td>
  #       <td class="post-category">Rails</td><td class="author">John Q. Public</td>
  #       <td class="post-publish_date">21 days</td>
  #       <td class="post-num_comments">-</td>
  #       <td class="post-num_trackbacks">-</td>
  #     </tr>
  #   </tbody>
  #   <tfoot>
  #     <tr>
  #       <td class="post-num_comments">0</td>
  #       <td class="post-num_trackbacks" colspan="5">0</td>
  #     </tr>
  #   </tfoot>
  #   <table>
  def collection_table(collection, klass = nil, html_options = {}, &block)
    CollectionTable.new(collection, klass, html_options, &block).html
  end
end

ActionController::Base.class_eval do
  helper TableHelper
end
